package com.soma.game.utils;


import org.bouncycastle.jce.provider.BouncyCastleProvider;

import java.security.*;
import java.security.spec.ECGenParameterSpec;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.util.Map;
import java.util.TreeMap;
import java.util.UUID;

/**
 * @program: soma-game
 * @description: 签名
 * @author: hduprince
 * @create: 2018-08-16 15:30
 **/
public class SignUtil {

    private static long appId = 10001L;
    private static String privateKey =
            "30818d020100301006072a8648ce3d020106052b8104000a0476307402010104201301e689b1adf7a705228a1699e6e553106f1c4d88b7a518d05fb17ea88a32a8a00706052b8104000aa144034200043f925c0bb9c3273ff07a0a66af8b6ed460494e51cbdf128489bb46588b44249c15c3cdabc91f64bfcde4292a47291691eb82eae216351f5841caba9c619e2cd8";

    static {
        Security.addProvider(new BouncyCastleProvider());
    }

    public static KeyPair generateKeyPair() throws NoSuchAlgorithmException, InvalidAlgorithmParameterException,
            NoSuchProviderException {
        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("EC", "BC");
        ECGenParameterSpec ecGenParameterSpec = new ECGenParameterSpec("secp256k1");
        keyPairGenerator.initialize(ecGenParameterSpec, new SecureRandom());
        return keyPairGenerator.generateKeyPair();
    }

    public static byte[] sign(String privateKey, String content)
            throws NoSuchAlgorithmException, InvalidKeySpecException, InvalidKeyException, SignatureException,
            NoSuchProviderException {
        PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(HexUtil.fromHex(privateKey));
        KeyFactory keyFactory = KeyFactory.getInstance("EC", "BC");
        PrivateKey priKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
        Signature signature = Signature.getInstance("SHA256withECDSA");
        signature.initSign(priKey);
        signature.update(content.getBytes());
        return signature.sign();
    }

    private static String content(long appId, long ts, String nonce) {
        Map<String, Object> paramMap = new TreeMap<String, Object>();
        paramMap.put("app_id", appId);
        paramMap.put("ts", ts);
        paramMap.put("nonce", nonce);
        StringBuilder sb = new StringBuilder();
        for (Map.Entry<String, Object> entry : paramMap.entrySet()) {
            String key = entry.getKey();
            Object value = entry.getValue();
            sb.append(key);
            sb.append(value);
        }
        return sb.toString();
    }

    public static String sign(long ts, String nonce)
            throws InvalidKeySpecException, NoSuchProviderException
            , NoSuchAlgorithmException, InvalidKeyException, SignatureException {
        return HexUtil.toHex(sign(privateKey, content(appId, ts, nonce)));
    }

    public static void main(String[] args)
            throws InvalidKeySpecException, NoSuchProviderException, NoSuchAlgorithmException
            , InvalidKeyException, SignatureException, InvalidAlgorithmParameterException {

        // 下面是生成公私钥的方式, 私钥第三方用于请求签名, 公钥 SOMA 用于验签
        KeyPair keyPair = generateKeyPair();
        String privateKey = HexUtil.toHex(keyPair.getPrivate().getEncoded());
        String publicKey = HexUtil.toHex(keyPair.getPublic().getEncoded());

        System.out.println("***private key***\n" + privateKey);
        System.out.println("***public key***\n" + publicKey);

        // 样例如下
        long ts = System.currentTimeMillis();
        System.out.println("ts :::" + ts);
        String nonce = UUID.randomUUID().toString().replaceAll("-", "");
        System.out.println("nonce ::: " + nonce);
        String sign = sign(ts, nonce);
        System.out.println("sign ::: " + sign);

        // 具体的请求式样需要携带参数
        // "app_id": appId
        // "ts": ts
        // "nonce": nonce
        // "sign": sign
        // 其他业务参数 ... ...


    }

    public static void getParma(Map<String, String> business){


        long ts = System.currentTimeMillis();
        System.out.println("ts :::" + ts);
        business.put("ts", ts+"");
        String nonce = UUID.randomUUID().toString().replaceAll("-", "");
        System.out.println("nonce ::: " + nonce);
        business.put("nonce", nonce);
        business.put("app_id", appId+"");
        try {
            String sign = sign(ts, nonce);
            business.put("sign", sign);
        } catch (InvalidKeySpecException e) {
            e.printStackTrace();
        } catch (NoSuchProviderException e) {
            e.printStackTrace();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (InvalidKeyException e) {
            e.printStackTrace();
        } catch (SignatureException e) {
            e.printStackTrace();
        }
    }
}
